package org.tea.inventory.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.tea.inventory.base.exception.ApplicationException;
import org.tea.inventory.base.util.StringUtils;
import org.tea.inventory.cache.constans.CacheConstants;
import org.tea.inventory.cache.utils.RedisUtil;
import org.tea.inventory.dao.sys.SysDeptMapper;
import org.tea.inventory.dao.sys.UserInfoMapper;
import org.tea.inventory.dao.tea.*;
import org.tea.inventory.db.service.AlumniRecordStorageService;
import org.tea.inventory.domain.sys.SysDept;
import org.tea.inventory.domain.sys.UserInfo;
import org.tea.inventory.domain.tea.*;
import org.tea.inventory.model.vo.SupplierInfoVo;
import org.tea.inventory.model.vo.WarehouseInventorySerialVo;
import org.tea.inventory.service.IWarehouseInventorySerialService;
import org.tea.inventory.utils.UserUtil;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 仓库库存流水Service业务层处理
 * 
 * @author dongxb
 * @date 2025-04-16
 */
@Service
@Slf4j
public class WarehouseInventorySerialServiceImpl implements IWarehouseInventorySerialService
{
    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private AlumniRecordStorageService storageService;

    @Autowired
    private StoreInfoMapper storeInfoMapper;

    @Autowired
    private SysDeptMapper deptMapper;

    @Autowired
    private SupplierMessageMapper supplierMessageMapper;

    @Autowired
    private WarehouseInfoMapper warehouseInfoMapper;

    @Autowired
    private WarehouseInventoryMapper warehouseInventoryMapper;

    @Autowired
    private WarehouseInventorySerialMapper warehouseInventorySerialMapper;

    @Autowired
    private WarehouseInventorySerialInfoMapper warehouseInventorySerialInfoMapper;

    /**
     * 查询仓库库存流水
     * 
     * @param id 仓库库存流水主键
     * @return 仓库库存流水
     */
    @Override
    public WarehouseInventorySerialVo selectWarehouseInventorySerialById(Long id)
    {
        WarehouseInventorySerialVo vo = warehouseInventorySerialMapper.selectWarehouseInventorySerialById(id);
        setViewDataByType(vo);

        //维护文件对象    只有详情页面才需要返回文件对象，使用不在setViewDataByType方法中赋值
        if (vo.getFileIds() != null) vo.setFiles(storageService.selectByPrimaryKeys(vo.getFileIds().split(",")));

        Long serialId = vo.getId();
        Long warehouseId = vo.getWarehouseId();
        String updateType = "1";
        List<WarehouseInventorySerialInfo> serialInfos = warehouseInventorySerialInfoMapper.selectInfoList(serialId , warehouseId , null);
        ArrayList<WarehouseInventorySerialInfo> entryList = new ArrayList<>();
        ArrayList<WarehouseInventorySerialInfo> outList = new ArrayList<>();
        serialInfos.stream().forEach(bean -> {
            if ("1".equals(bean.getUpdateType())) {
                //入库
                entryList.add(bean);
            } else if ("2".equals(bean.getUpdateType())) {
                //出库
                outList.add(bean);
            }
        });
        vo.setInventoryEntryInfos(entryList);
        vo.setInventoryOutInfos(outList);
        return vo;
    }

    private void setViewDataByType(WarehouseInventorySerialVo vo) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        vo.setSerialDateStr(format.format(vo.getSerialDate()));

        String type = vo.getSerialType();
        String isRunFinishStr = "";
        if ("1".equals(type)) {
            isRunFinishStr = vo.getIsRunFinish() == 0 ? "已入库" : "待入库";
        } else if ("2".equals(type) || "3".equals(type) || "4".equals(type)) {
            isRunFinishStr = vo.getIsRunFinish() == 0 ? "已发货" : "待发货";
        } else if ("6".equals(type)) {
            isRunFinishStr = vo.getIsRunFinish() == 0 ? "已组装" : "待组装";
        } else if ("7".equals(type)) {
            isRunFinishStr = vo.getIsRunFinish() == 0 ? "已拆卸" : "待拆卸";
        }
        vo.setIsRunFinishStr(isRunFinishStr);

        //通用赋值
        //查询仓库名称
        WarehouseInfo warehouseInfo = warehouseInfoMapper.selectWarehouseInfoById(vo.getWarehouseId());
        if (warehouseInfo != null) vo.setWarehouseName(warehouseInfo.getWarehouseName());

        //查询经手人名称
        String userName = userInfoMapper.selectUserNameByLognId(vo.getAddHandlerId());
        if (userName != null) vo.setAddHandlerName(userName);

        if ("1".equals(type)) {
            //入库单
            //查询供应商名称
            SupplierInfoVo supplierInfoVo = supplierMessageMapper.selectSupplierMessageById(vo.getSupplierId());
            if (supplierInfoVo != null) vo.setSupplierName(supplierInfoVo.getSupplierName());
        } else if ("2".equals(type)) {
            //出库单
            //要货部门
            SysDept sysDept = deptMapper.selectDeptById(vo.getRequireDepartmentId());
            if (sysDept != null) vo.setRequireDepartmentName(sysDept.getDeptName());

            //门店
            StoreInfo storeInfo = storeInfoMapper.selectStoreInfoById(vo.getStoreId());
            if (storeInfo != null) vo.setStoreName(storeInfo.getStoreName());

            //查询经手人名称
            String outUserName = userInfoMapper.selectUserNameByLognId(vo.getOutHandlerId());
            if (outUserName != null) vo.setOutHandlerName(outUserName);
        } else if ("3".equals(type)) {
            //调拨单
            //调出经手人名称
            String out = userInfoMapper.selectUserNameByLognId(vo.getOutHandlerId());
            if (out != null) vo.setOutHandlerName(out);

            //调入仓库名称
            WarehouseInfo target = warehouseInfoMapper.selectWarehouseInfoById(vo.getWarehouseTargetId());
            if (target != null) vo.setWarehouseTargetName(target.getWarehouseName());
        } else if ("6".equals(type) || "7".equals(type)) {
            //组装/拆卸商品名称
            Product product = productMapper.selectProductById(vo.getAssembleProductId());
            if (product != null) vo.setAssembleProductName(product.getProductName());
        }
    }

    /**
     * 查询仓库库存流水列表
     * 
     * @param warehouseInventorySerialVo 仓库库存流水
     * @return 仓库库存流水
     */
    @Override
    public List<WarehouseInventorySerialVo> selectWarehouseInventorySerialList(WarehouseInventorySerialVo warehouseInventorySerialVo)
    {
        warehouseInventorySerialVo.setDelFlag(0);
        List<WarehouseInventorySerialVo> serialVos = warehouseInventorySerialMapper.selectWarehouseInventorySerialList(warehouseInventorySerialVo);
        serialVos.stream().forEach(bean -> {
            setViewDataByType(bean);
        });
        return serialVos;
    }

    /**
     * 新增仓库库存流水
     * 
     * @param warehouseInventorySerialVo 仓库库存流水
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertWarehouseInventorySerial(WarehouseInventorySerialVo warehouseInventorySerialVo , String type)
    {
        Date date = new Date();
        UserInfo user = UserUtil.getUser();
        if ("update".equals(type)) {
            warehouseInventorySerialVo.setUpdateUser(UserUtil.getUser().getLoginId());
            warehouseInventorySerialVo.setUpdateDate(new Date());
        } else {
            warehouseInventorySerialVo.setSerialCode(getCode(warehouseInventorySerialVo.getSerialType()));
            warehouseInventorySerialVo.setCreateUser(UserUtil.getUser().getLoginId());
            warehouseInventorySerialVo.setCreateDate(new Date());
        }
        int result = warehouseInventorySerialMapper.insertWarehouseInventorySerial(warehouseInventorySerialVo);
        log.info("insert id=" + warehouseInventorySerialVo.getId());
        List<WarehouseInventorySerialInfo> inventoryEntryInfos = warehouseInventorySerialVo.getInventoryEntryInfos();
        if (inventoryEntryInfos != null && inventoryEntryInfos.size() >= 1) {
            warehouseInventorySerialVo.getInventoryEntryInfos().stream().forEach(bean -> {
                bean.setUpdateType("1");
                bean.setSerialId(warehouseInventorySerialVo.getId());
                bean.setCreateUserId(user.getLoginId());
                bean.setCreateDate(date);
                warehouseInventorySerialInfoMapper.insertWarehouseInventorySerialInfo(bean);
            });
        }

        List<WarehouseInventorySerialInfo> inventoryOutInfos = warehouseInventorySerialVo.getInventoryOutInfos();
        if (inventoryOutInfos != null && inventoryOutInfos.size() >= 1) {
            warehouseInventorySerialVo.getInventoryOutInfos().stream().forEach(bean -> {
                bean.setUpdateType("2");
                bean.setSerialId(warehouseInventorySerialVo.getId());
                bean.setCreateUserId(user.getLoginId());
                bean.setCreateDate(date);
                warehouseInventorySerialInfoMapper.insertWarehouseInventorySerialInfo(bean);
            });
        }

        //判断是否是拆卸单，如果是则需要判断状态是否为执行，如果为执行则需要更新库存信息
        if ("6".equals(warehouseInventorySerialVo.getSerialType()) || "7".equals(warehouseInventorySerialVo.getSerialType())) {
            if ("1".equals(warehouseInventorySerialVo.getIsRunFinish())) {
                //是否执行状态为1则表示需要执行
                assemblyOrDisassembly(warehouseInventorySerialVo, inventoryOutInfos , inventoryEntryInfos , date ,user);
            }
        }

        return result;
    }
    /**
     * 新增仓库库存流水
     *
     * @param warehouseInventorySerialVo 仓库库存流水
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertWarehouseInventorySerial(WarehouseInventorySerialVo warehouseInventorySerialVo)
    {
        return insertWarehouseInventorySerial(warehouseInventorySerialVo , "insert");
    }

    /**
     * 组装或拆卸方法
     *
     * @param inventoryVo 单据信息
     * @param outInfos    组装明细对象
     * @param entryInfos  拆卸明细对象
     * @param date        时间
     * @param user        当前登录用户
     */
    private void assemblyOrDisassembly(WarehouseInventorySerialVo inventoryVo, List<WarehouseInventorySerialInfo> outInfos, List<WarehouseInventorySerialInfo> entryInfos, Date date, UserInfo user) {
        if (inventoryVo == null) throw new ApplicationException(-1, "单据处理出错：该单据数据有误");
        if ("6".equals(inventoryVo.getSerialType())) {
            if (outInfos == null && outInfos.size() >= 0) {
                throw new ApplicationException(-1, "单据处理出错：当前单据无出组装数据");
            } else {
                outInfos.stream().forEach(bean -> {
                    bean.setUpdateNumber(bean.getUpdateNumber() * inventoryVo.getUpdateNumber());
                });
            }
        }
        if ("7".equals(inventoryVo.getSerialType())) {
            if (entryInfos == null && entryInfos.size() >= 0) {
                throw new ApplicationException(-1, "单据处理出错：当前单据无出拆卸数据");
            } else {
                entryInfos.stream().forEach(bean -> {
                    bean.setUpdateNumber(bean.getUpdateNumber() * inventoryVo.getUpdateNumber());
                });
            }
        }

        //维护组装/拆卸的商品信息
        WarehouseInventorySerialInfo serialInfo = new WarehouseInventorySerialInfo();
        serialInfo.setSerialId(inventoryVo.getId());
        serialInfo.setProductId(inventoryVo.getAssembleProductId());
        serialInfo.setUpdateNumber(inventoryVo.getUpdateNumber().longValue());

        //组装单
        if ("6".equals(inventoryVo.getSerialType())) {
            //先出库需要用于组装的商品
            try {
                outInventory(inventoryVo.getWarehouseId(), outInfos , date , user);
            } catch (Exception e) {
                throw new ApplicationException(-1, "商品库存不足，无法进行组装");
            }

            //再入库组装的商品
            entryInfos = new ArrayList<>();
            entryInfos.add(serialInfo);
            entryInventory(inventoryVo.getWarehouseId(), entryInfos , date , user);
        } else if ("7".equals(inventoryVo.getSerialType())) {
            //出库单
            //先出库组装的商品
            WarehouseInventory inventory = warehouseInventoryMapper.getInventory(inventoryVo.getWarehouseId(), inventoryVo.getAssembleProductId());
            serialInfo.setCreateProductNumber(inventory.getProductNumber());

            outInfos = new ArrayList<>();
            outInfos.add(serialInfo);
            try {
                outInventory(inventoryVo.getWarehouseId(), outInfos , date , user);
            } catch (Exception e) {
                throw new ApplicationException(-1, "商品库存不足，无法进行拆卸");
            }

            //再入库需要用于组装的商品
            entryInventory(inventoryVo.getWarehouseId(), entryInfos , date , user);
        }
    }

    private String getCode(String type){
        StringBuilder result = new StringBuilder();
        result.append(CacheConstants.SERIAL_CODE_KEY);
        //拼接前缀
        switch (type) {
            case "1":
                //入库单
                result.append("RK");
                break;
            case "2":
                //出库单
                result.append("CK");
                break;
            case "3":
                //调拨单
                result.append("DB");
                break;
            case "4":
                //换货单
                result.append("HH");
                break;
            case "5":
                //报损单
                result.append("BS");
                break;
            case "6":
                //组装单
                result.append("ZZ");
                break;
            case "7":
                //拆卸单
                result.append("CX");
                break;
            case "0":
                //盘点单
                result.append("PD");
                break;
            default:
                result = null;
        }
        String date = new SimpleDateFormat("yyyyMM").format(new Date());
        //拼接时间
        result.append(date);

        //拼接流水号
        //查询redis 如果没有则从1开始存储
        String serial = RedisUtil.getStr(result.toString());
        log.info("redis serial=" + serial);
        if (StringUtils.isBlank(serial)) {
            RedisUtil.setExpireDay(result.toString() , 1 , 31);
            serial = "001";
        } else {
            int parseInt = Integer.parseInt(serial);
            if (parseInt >= 999) parseInt = 0;
            parseInt++;
            serial = String.format("%03d", parseInt);
            //将新流水号存入redis
            RedisUtil.setExpireDay(result.toString() , parseInt , 31);
        }
        result.append(serial);
        String returnStr = result.toString().substring(result.toString().indexOf("code:") + 5);
        log.info("getCode=" + returnStr);
        return returnStr;
    }

    /**
     * 修改仓库库存流水
     * 
     * @param warehouseInventorySerialVo 仓库库存流水
     * @return 结果
     */
    @Override
    @Transactional
    public int updateWarehouseInventorySerial(WarehouseInventorySerialVo warehouseInventorySerialVo)
    {
        warehouseInventorySerialMapper.deleteWarehouseInventorySerialById(warehouseInventorySerialVo.getId());
        warehouseInventorySerialInfoMapper.deleteBySerialId(warehouseInventorySerialVo.getId());
        return insertWarehouseInventorySerial(warehouseInventorySerialVo , "update");
    }

    /**
     * 批量删除仓库库存流水
     * 
     * @param ids 需要删除的仓库库存流水主键
     * @return 结果
     */
    @Override
    public int deleteWarehouseInventorySerialByIds(Long[] ids)
    {
        return warehouseInventorySerialMapper.deleteWarehouseInventorySerialByIds(ids);
    }

    /**
     * 删除仓库库存流水信息
     * 
     * @param id 仓库库存流水主键
     * @return 结果
     */
    @Override
    public int deleteWarehouseInventorySerialById(Long id)
    {
        return warehouseInventorySerialMapper.deleteWarehouseInventorySerialById(id);
    }
    /**
     * 获取仓库中商品库存信息(分页)
     */
    @Override
    public List<WarehouseInventorySerialInfo> getWarehouseInventory(Long warehouseId , String type , String keyword) {
        List<WarehouseInventorySerialInfo> warehouseInventorySerialInfos = new ArrayList<>();
        if (!"2".equals(type)) {
            //查询所有商品信息
            Product product = new Product();
            product.setStatus(0);
            product.setProductName(keyword);
            product.setDelFlag(0);
            List<Product> products = productMapper.selectProductList(product);
            if (products != null && products.size() >= 1){
                products.stream().forEach(bean -> {
                    //查询库存
                    WarehouseInventory warehouseInventory = warehouseInventoryMapper.getInventory(warehouseId , bean.getId());

                    WarehouseInventorySerialInfo inventory = new WarehouseInventorySerialInfo();
                    inventory.setId(warehouseInventory == null ? bean.getId() : warehouseInventory.getId());
                    inventory.setProductId(bean.getId());
                    inventory.setProductCode(bean.getProductCode());
                    inventory.setProductName(bean.getProductName());
                    //若没有库存信息则按库存为0处理
                    inventory.setCreateProductNumber(warehouseInventory == null ? Long.valueOf(0) : warehouseInventory.getProductNumber());
                    inventory.setCreatePrice(bean.getPrice());
                    warehouseInventorySerialInfos.add(inventory);
                });
            }
        } else if ("2".equals(type)) {
            //只查询本仓库中有库存的商品信息
            WarehouseInventory query = new WarehouseInventory();
            query.setWarehouseId(warehouseId);
            query.setProductName(keyword);
            List<WarehouseInventory> inventories = warehouseInventoryMapper.selectWarehouseInventoryListByName(query);
            inventories.stream().forEach(bean -> {
                if (bean.getProductNumber() >= 1) {
                    Product product = productMapper.selectProductById(bean.getProductId());
                    WarehouseInventorySerialInfo inventory = new WarehouseInventorySerialInfo();
                    inventory.setId(bean.getId());
                    inventory.setProductId(product.getId());
                    inventory.setProductCode(product.getProductCode());
                    inventory.setProductName(product.getProductName());
                    //若没有库存信息则按库存为0处理
                    inventory.setCreateProductNumber( bean.getProductNumber());
                    inventory.setCreatePrice(product.getPrice());
                    warehouseInventorySerialInfos.add(inventory);
                }
            });
        }

        return warehouseInventorySerialInfos;
    }

    /**
     * 根据仓库Id获取仓库中商品信息
     */
    @Override
    public List<WarehouseInventorySerialInfo> getWarehouseProduct(Long warehouseId) {
        return getWarehouseInventory(warehouseId , warehouseId == null ? "1" : "2" , null);
    }

    /**
     * 执行流水相关操作
     *
     * @param ids 流水主键id集合
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int execute(Long[] ids) {
        for (int i = 0; i < ids.length; i++) {
            WarehouseInventorySerialInfo query = new WarehouseInventorySerialInfo();
            query.setSerialId(ids[i]);
            List<WarehouseInventorySerialInfo> inventorySerialInfos = warehouseInventorySerialInfoMapper.selectWarehouseInventorySerialInfoList(query);
            if (inventorySerialInfos == null && inventorySerialInfos.size() >= 0) throw new ApplicationException(-1, "单据处理出错：当前单据无出入库数据");

            Date date = new Date();
            UserInfo user = UserUtil.getUser();
            WarehouseInventorySerialVo inventorySerial = warehouseInventorySerialMapper.selectWarehouseInventorySerialById(ids[i]);

            //根据不同的id做不同的处理
            if ("1".equals(inventorySerial.getSerialType())) {
                //入库 仓库id为本仓库
                entryInventory(inventorySerial.getWarehouseId() , inventorySerialInfos , date , user);
            } else if ("2".equals(inventorySerial.getSerialType())) {
                //出库单
                //出库 仓库id为本仓库
                outInventory(inventorySerial.getWarehouseId() , inventorySerialInfos , date , user);
            } else if ("3".equals(inventorySerial.getSerialType())) {
                //调拨单
                //先减库存  出库 仓库id为调出仓库id
                try {
                    outInventory(inventorySerial.getWarehouseId() , inventorySerialInfos , date , user);
                } catch (Exception e) {
                    throw new ApplicationException(-1, "商品库存不足，无法进行调拨");
                }
                //再加库存  入库  仓库id为目标仓库id
                entryInventory(inventorySerial.getWarehouseTargetId() , inventorySerialInfos , date , user);
            } else if ("4".equals(inventorySerial.getSerialType())) {
                //换货单
                List<WarehouseInventorySerialInfo> entry = new ArrayList<>();
                List<WarehouseInventorySerialInfo> out = new ArrayList<>();
                inventorySerialInfos.stream().forEach(bean -> {
                    if ("1".equals(bean.getUpdateType())) {
                        entry.add(bean);
                    } else if ("2".equals(bean.getUpdateType())) {
                        out.add(bean);
                    }
                });
                //先减库存  出库 仓库id为本仓库id
                try {
                    outInventory(inventorySerial.getWarehouseId() , out , date , user);
                } catch (Exception e) {
                    throw new ApplicationException(-1, "商品库存不足，无法进行换货");
                }
                //再加库存  入库  仓库id为本仓库id
                entryInventory(inventorySerial.getWarehouseId() , entry , date , user);
            } else if ("5".equals(inventorySerial.getSerialType())) {
                //报损单
                try {
                    outInventory(inventorySerial.getWarehouseId() , inventorySerialInfos , date , user);
                } catch (Exception e) {
                    throw new ApplicationException(-1, "商品库存不足，无法进行报损");
                }
            }  else if ("6".equals(inventorySerial.getSerialType())) {
                //组装单
                assemblyOrDisassembly(inventorySerial , inventorySerialInfos , null , date , user);
            } else if ("7".equals(inventorySerial.getSerialType())) {
                //拆卸单
                assemblyOrDisassembly(inventorySerial , null , inventorySerialInfos , date , user);
            }

            //执行完毕后将状态改为执行完成
            WarehouseInventorySerialVo updateInventory = new WarehouseInventorySerialVo();
            updateInventory.setId(ids[i]);
            updateInventory.setIsRunFinish(0);
            updateInventory.setIsDelivery(0);
            warehouseInventorySerialMapper.updateWarehouseInventorySerial(updateInventory);
        }

        return ids.length;
    }

    /**
     * 作废流水相关操作
     *
     * @param id 流水主键id集合
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int cancel(Long id, String cancelMsg) {
        WarehouseInventorySerialInfo query = new WarehouseInventorySerialInfo();
        query.setSerialId(id);
        List<WarehouseInventorySerialInfo> inventorySerialInfos = warehouseInventorySerialInfoMapper.selectWarehouseInventorySerialInfoList(query);
        if (inventorySerialInfos == null && inventorySerialInfos.size() >= 0) throw new ApplicationException(-1, "单据处理出错：当前单据无出入库数据");

        Date date = new Date();
        UserInfo user = UserUtil.getUser();
        WarehouseInventorySerialVo inventorySerial = warehouseInventorySerialMapper.selectWarehouseInventorySerialById(id);
        if (inventorySerial == null) throw new ApplicationException(-1, "单据处理出错：当前单据无出入库数据");

        if ("6".equals(inventorySerial.getSerialType()) || "7".equals(inventorySerial.getSerialType())) {
            inventorySerial.setSerialType(inventorySerial.getSerialType() == "6" ? "7" : "6");
        }

        //根据不同的id做不同的处理
        if ("1".equals(inventorySerial.getSerialType())) {
            //入库 仓库id为本仓库
            //需要将入库的数据进行出库
            try {
                outInventory(inventorySerial.getWarehouseId() , inventorySerialInfos , date , user);
            } catch (Exception e) {
                throw new ApplicationException(-1, "商品库存不足，无法进行作废");
            }
        } else if ("2".equals(inventorySerial.getSerialType())) {
            //出库单
            //出库 仓库id为本仓库
            //需要将出库的数据进行入库
            entryInventory(inventorySerial.getWarehouseId() , inventorySerialInfos , date , user);
        } else if ("3".equals(inventorySerial.getSerialType())) {
            //调拨单
            //先减库存  出库 仓库id为目标仓库id
            try {
                outInventory(inventorySerial.getWarehouseTargetId() , inventorySerialInfos , date , user);
            } catch (Exception e) {
                throw new ApplicationException(-1, "商品库存不足，无法进行作废");
            }
            //再加库存  入库  仓库id为调出仓库id
            entryInventory(inventorySerial.getWarehouseId() , inventorySerialInfos , date , user);
        } else if ("4".equals(inventorySerial.getSerialType())) {
            //换货单
            List<WarehouseInventorySerialInfo> entry = new ArrayList<>();
            List<WarehouseInventorySerialInfo> out = new ArrayList<>();
            inventorySerialInfos.stream().forEach(bean -> {
                if ("1".equals(bean.getUpdateType())) {
                    entry.add(bean);
                } else if ("2".equals(bean.getUpdateType())) {
                    out.add(bean);
                }
            });
            //先减库存  出库 仓库id为本仓库id
            try {
                outInventory(inventorySerial.getWarehouseId() , entry , date , user);
            } catch (Exception e) {
                throw new ApplicationException(-1, "商品库存不足，无法进行作废");
            }
            //再加库存  入库  仓库id为本仓库id
            entryInventory(inventorySerial.getWarehouseId() , out , date , user);
        } else if ("5".equals(inventorySerial.getSerialType())) {
            //报损单
            try {
                entryInventory(inventorySerial.getWarehouseId() , inventorySerialInfos , date , user);
            } catch (Exception e) {
                throw new ApplicationException(-1, "商品库存不足，无法进行作废");
            }
        }  else if ("6".equals(inventorySerial.getSerialType())) {
            //组装单
            try {
                assemblyOrDisassembly(inventorySerial , inventorySerialInfos , null , date , user);
            } catch (Exception e) {
                throw new ApplicationException(-1, "商品库存不足，无法进行作废");
            }
        } else if ("7".equals(inventorySerial.getSerialType())) {
            //拆卸单
            try {
                assemblyOrDisassembly(inventorySerial , null , inventorySerialInfos , date , user);
            } catch (Exception e) {
                throw new ApplicationException(-1, "商品库存不足，无法进行作废");
            }
        }

        //执行完毕后更改状态
        WarehouseInventorySerialVo updateInventory = new WarehouseInventorySerialVo();
        updateInventory.setId(id);
        //执行标志赋值为2 已作废
        updateInventory.setIsRunFinish(2);
        updateInventory.setIsDelivery(2);
        updateInventory.setCancelMsg(cancelMsg);
        return warehouseInventorySerialMapper.updateWarehouseInventorySerial(updateInventory);
    }


    /**
     *  执行出库操作方法
     * @param warehouseId 目标仓库id
     * @param inventorySerialInfos  出库明细数据
     * @param date  执行时间
     * @param user  执行人
     */
    private void outInventory(Long warehouseId, List<WarehouseInventorySerialInfo> inventorySerialInfos , Date date, UserInfo user) {
        //出库单
        inventorySerialInfos.stream().forEach(bean -> {
            Long productId = bean.getProductId();
            WarehouseInventory updateInventory = warehouseInventoryMapper.getInventory(warehouseId, productId);
            if (updateInventory == null) throw new ApplicationException(-1, "该商品已无库存，无法进行出库");
            if (updateInventory.getProductNumber() < bean.getUpdateNumber()) throw new ApplicationException(-1, "出库数量大于当前库存数量，无法进行出库");

            //维护新库存
            updateInventory.setProductNumber((updateInventory.getProductNumber() - bean.getUpdateNumber()));
            updateInventory.setUpdateUserId(user.getLoginId());
            updateInventory.setUpdateDate(date);
            warehouseInventoryMapper.updateWarehouseInventory(updateInventory);
        });
    }

    /**
     *  执行入库操作方法
     * @param warehouseId 目标仓库id
     * @param inventorySerialInfos  入库明细数据
     * @param date  执行时间
     * @param user  执行人
     */
    private void entryInventory(Long warehouseId, List<WarehouseInventorySerialInfo> inventorySerialInfos , Date date, UserInfo user) {

        inventorySerialInfos.stream().forEach(bean -> {
            Long productId = bean.getProductId();
            WarehouseInventory updateInventory = warehouseInventoryMapper.getInventory(warehouseId, productId);
            if (updateInventory == null) {
                WarehouseInventory insertInventory = new WarehouseInventory();
                insertInventory.setWarehouseId(warehouseId);
                insertInventory.setProductId(productId);
                insertInventory.setProductNumber(bean.getUpdateNumber());
                insertInventory.setCreateUserId(user.getLoginId());
                insertInventory.setCreateDate(date);
                warehouseInventoryMapper.insertWarehouseInventory(insertInventory);
            } else {
                updateInventory.setProductNumber((updateInventory.getProductNumber() + bean.getUpdateNumber()));
                updateInventory.setUpdateUserId(user.getLoginId());
                updateInventory.setUpdateDate(date);
                warehouseInventoryMapper.updateWarehouseInventory(updateInventory);
            }
        });
    }
}
